package com.moyoutian.line.link;

import java.util.Objects;

/**
 * 单向链表
 */
public class SingleLinkList1<D> {

    public Node getHeader() {
        return header;
    }

    public void setHeader(Node header) {
        this.header = header;
    }

    private Node header;

    private Node tail;

    public class Node {

        public D getData() {
            return data;
        }

        public void setData(D data) {
            this.data = data;
        }

        /**
         * 节点数据
         */
        private D data;

        public Node getNextNode() {
            return nextNode;
        }

        public void setNextNode(Node nextNode) {
            this.nextNode = nextNode;
        }

        /**
         * 下一个节点
         */
        private Node nextNode;

        public Node() {
        }

        public Node(D data) {
            this.data = data;
        }
    }


    public SingleLinkList1() {
    }

    /**
     * @param headerData 头结点中的数据
     */
    public SingleLinkList1(D headerData) {
        addToTail(headerData);
    }

    /**
     * 添加元素
     *
     * @param d 数据
     */
    public void addToTail(D d) {
        if (header == null) {
            header = new Node(d);
            tail = header;
        } else {
            tail.nextNode = new Node(d);
            tail = tail.nextNode;
        }
        tail.nextNode = header;
    }

    /**
     * 添加元素
     *
     * @param d 数据
     */
    public void addToHeader(D d) {
        addToHeader(new Node(d));
    }

    /**
     * 添加元素
     *
     * @param node 数据
     */
    public void addToHeader(Node node) {
        if (header == null) {
            header = node;
            tail = header;
        } else {
            // 先将新结点的下一个坐标指向头结点
            node.nextNode = header;
            // 重置头结点
            header = node;
        }
    }

    public void remove(D data) {
        Node tempNode = header;
        if (header != null) {
            // 删除头结点
            if (header.data.equals(data)) {
                header = tempNode.nextNode;
            } else {
                //删除非头结点
                while (tempNode.nextNode != null && tempNode.nextNode != header) {
                    // 如果当前结点的下个结点满足条件，就将当前结点的指针指向当前结点的下下个结点（下下个结点为空也没事）
                    if (Objects.equals(tempNode.nextNode.data, data)) {
                        if (tempNode.nextNode == tail) {
                            tail = tempNode;
                            tempNode.nextNode = null;
                        } else {
                            tempNode.nextNode = tempNode.nextNode.nextNode;
                        }
                        return;
                    }
                    tempNode = tempNode.nextNode;
                }
            }
        }
    }


    public void removeIndex(int index) {
        Node tempNode = header;
        int tempIndex = 1;
        if (header != null) {
            // 删除头结点
            if (index == 1) {
                header = tempNode.nextNode;
            }
            //删除非头结点
            while (tempNode.nextNode != null && tempNode.nextNode != header) {
                // 如果当前结点的下个结点满足条件，就将当前结点的指针指向当前结点的下下个结点（下下个结点为空也没事）
                if (tempIndex++ == index) {
                    if (tempNode.nextNode == tail) {
                        tail = tempNode;
                        tempNode.nextNode = null;
                    } else {
                        tempNode.nextNode = tempNode.nextNode.nextNode;
                    }
                    return;
                }
                tempNode = tempNode.nextNode;
            }
        }
    }

    public boolean isEntity() {
        return header == null;
    }

    public void reverse() {
        Node temp = header;
        header = null;
        while (temp != null) {
            Node next = temp.nextNode;
            temp.nextNode = null;
            addToHeader(temp);
            temp = next;
        }
    }


    public void toStr() {
        Node temp = header;
        while (temp != tail) {
            System.out.println("D:" + temp.data);
            temp = temp.nextNode;
        }
        System.out.println("D:" + tail.data);

    }

}
